﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;

namespace WindowService
{
    public class HttpServer
    {
        public delegate string serviceDelegate(HttpListenerContext httpListenerContext);
        private HttpListener httpListener = null;
        public HttpServer(string port, Dictionary<string, serviceDelegate> package)
        {
            string Url = "http://+:" + port + "/";
            Log.WriteLog("HttpServer Start service URL:" + Url, LogType.Trace);
            httpListener = new HttpListener();

            try
            {
                if (!httpListener.IsListening)
                {
                    httpListener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                    httpListener.Prefixes.Add(Url);
                    httpListener.Start();
                }
                else
                {
                    Log.WriteLog("HttpServer URL:" + Url + "was Listening", LogType.Trace);
                }
                new Thread(new ThreadStart(delegate
                {
                    while (true)
                    {
                        HttpListenerContext httpListenerContext = null;
                        try
                        {
                            httpListenerContext = httpListener.GetContext();
                            Guid guid = Guid.NewGuid();
                            string uuid = guid.ToString();
                            bool isResponse = false;

                            Log.WriteLog("HttpServer Req ID:" + uuid + " URL:" + httpListenerContext.Request.Url + " Method:" + httpListenerContext.Request.HttpMethod, LogType.Info);

                            foreach (var param in package)
                            {
                                if (httpListenerContext.Request.Url.AbsolutePath.Contains("/" + param.Key.ToString()))
                                {
                                    httpListenerContext.Response.StatusCode = 200;
                                    httpListenerContext.Response.ContentType = "application/jsonp";
                                    httpListenerContext.Response.ContentEncoding = Encoding.UTF8;

                                    using (StreamWriter writer = new StreamWriter(httpListenerContext.Response.OutputStream))
                                    {
                                        serviceDelegate callback = (serviceDelegate)param.Value;
                                        string response = callback(httpListenerContext);
                                        writer.WriteLine(response);

                                        Log.WriteLog("HttpServer Res ID:" + uuid + " Message:" + response, LogType.Info);
                                        isResponse = true;
                                    }
                                }
                            }

                            if (!isResponse)
                            {
                                httpListenerContext.Response.StatusCode = 404;
                                httpListenerContext.Response.ContentType = "apolication/json";
                                httpListenerContext.Response.ContentEncoding = Encoding.UTF8;

                                using (StreamWriter writer = new StreamWriter(httpListenerContext.Response.OutputStream))
                                {
                                    string response = "{\"errcode\":\"404\",\"errmsg\":\"can't find this page\",\"data\":[]}";
                                    writer.WriteLine(response);

                                    Log.WriteLog("HttpServer Res ID:" + uuid + " Message:" + response, LogType.Info);
                                }
                            }
                        }
                        catch (Exception e)
                        {
                            Log.WriteLog("httpListenerContext Get Context failed,  error:" + e.Message, LogType.Info);
                        }
                        finally
                        {
                            httpListenerContext = null;
                        }
                    }
                })).Start();
            }
            catch (Exception e)
            {
                Log.WriteLog("HttpServer init failed,  error:" + e.Message, LogType.Info);
            }
        }

        public static string _GET(HttpListenerContext httpListenerContext, string key, string defaultValue){
            for (int i = 0; i < httpListenerContext.Request.QueryString.Count; i++)
            {
                if (httpListenerContext.Request.QueryString.GetKey(i) == "callback")
                {
                    return httpListenerContext.Request.QueryString.Get(i);
                }
            }
            return defaultValue;
        }

        ~HttpServer()
        {
            if (httpListener != null)
            {
                httpListener.Close();
            }
            Log.WriteLog("HttpServer was closed", LogType.Info);
        }
    }
}